namespace Xsxiaosa.Net
{
    using System;
    using System.Collections;
//jyj add
	using System.Threading;

    internal class FtpDownloadStream : FtpStream
    {
        // Methods
        public FtpDownloadStream(Ftp ftp, bool disconnectOnClose, string remotePath) : base(ftp, disconnectOnClose)
        {
            this._queue = new Queue();
            this._length = 0;
            this._ftp.BeginGetFile(remotePath, this, new AsyncCallback(this.Finish), null);
            base.WaitForTransfer(FtpTransferState.Downloading);
        }

        public override void Close()
        {
            object obj1 = this._sync;
            lock (obj1)
            {
                if (this._closed)
                {
                    return;
                }
                this._closed = true;
            }
            this._ftp.Abort();
            base.ResetTimeout();
        Label_003B:
            obj1 = this._sync;
            lock (obj1)
            {
                if (!this._finished)
                {
                    goto Label_005B;
                }
                goto Label_009E;
            }
        Label_005B:
            if ((this._timeout > 0) && ((((long) Environment.TickCount) - this._timerStart) > ((long) this._timeout)))
            {
                throw new FtpException(Xsxiaosa.Net.Messages.GetString(typeof(FtpStrings), "Timeout"), FtpExceptionStatus.Timeout);
            }
            Thread.Sleep(1);
            goto Label_003B;
        Label_009E:
            if (this._disconnectOnClose)
            {
                this._ftp.Disconnect();
                this._ftp.Dispose();
            }
            GC.SuppressFinalize(this);
            if (this._exception == null)
            {
                return;
            }
            FtpException exception1 = (this._exception as FtpException);
            if (exception1 != null)
            {
                throw new FtpException(((FtpException) this._exception));
            }
            throw new FtpException(this._exception.Message, this._exception);
        }

        private void Finish(IAsyncResult ar)
        {
            object obj1;
            try
            {
                this._ftp.EndGetFile(ar);
            }
            catch (FtpException exception1)
            {
                if (exception1.Status != FtpExceptionStatus.OperationAborted)
                {
                    this._exception = exception1;
                    goto Label_0044;
                }
                try
                {
                    this._ftp.Flush(1000);
                    goto Label_0044;
                }
                catch
                {
                    goto Label_0044;
                }
            }
            catch (Exception exception2)
            {
                this._exception = exception2;
            }
        Label_0044:
            obj1 = this._sync;
            lock (obj1)
            {
                this._finished = true;
                base.TransferStarted = true;
            }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            int num1;
            Block block1;
            int num2;
//            int num3;
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer", Xsxiaosa.Net.Messages.GetString("ArgumentNullBuffer"));
            }
            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException("offset");
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("count");
            }
            if ((buffer.Length - offset) < count)
            {
                throw new ArgumentException(Xsxiaosa.Net.Messages.GetString("ArgumentInvalidOffset"));
            }
            object obj1 = this._sync;
            lock (obj1)
            {
                if (!this._closed)
                {
                    goto Label_0088;
                }
                throw new InvalidOperationException(Xsxiaosa.Net.Messages.GetString(typeof(FtpStrings), "StreamClosed"));
            }
        Label_0088:
            if (count == 0)
            {
                return 0;
            }
            base.ResetTimeout();
        Label_0093:
            obj1 = this._sync;
            lock (obj1)
            {
                if ((this._length == 0) && this._finished)
                {
                    if (this._exception != null)
                    {
                        throw this._exception;
                    }
                    return 0;
                }
                if (this._length <= 0)
                {
                    goto Label_00DC;
                }
                goto Label_00EA;
            }
        Label_00DC:
            base.CheckTimeout();
            Thread.Sleep(1);
            goto Label_0093;
        Label_00EA:
            num1 = 0;
            obj1 = this._sync;
            Monitor.Enter(obj1);
        Label_00FA:
            try
            {
                block1 = ((Block) this._queue.Peek());
                num2 = block1.Read(buffer, offset, count);
                if (block1.IsEmpty)
                {
                    this._queue.Dequeue();
                }
                num1 += num2;
                offset = (offset + num2);
                count = (count - num2);
                if ((this._queue.Count != 0) && (count > 0))
                {
                    goto Label_00FA;
                }
                this._length -= num1;
                return num1;
            }
            finally
            {
                Monitor.Exit(obj1);
            }
//jyj modify            return num3;
        }

        public override void WriteInternal(byte[] buffer, int offset, int count)
        {
            byte[] numArray1;
            Block block1;
            object obj1;
            if (count == 0)
            {
                return;
            }
        Label_0004:
            obj1 = this._sync;
            lock (obj1)
            {
                if (this._closed)
                {
                    return;
                }
                if (this._length >= 65536)
                {
                    goto Label_0033;
                }
                goto Label_003B;
            }
        Label_0033:
            Thread.Sleep(1);
            goto Label_0004;
        Label_003B:
            obj1 = this._sync;
            lock (obj1)
            {
                numArray1 = new byte[((uint) count)];
                Array.Copy(buffer, offset, numArray1, 0, count);
                block1 = new Block(numArray1);
                this._queue.Enqueue(block1);
                this._length += count;
            }
        }


        // Properties
        public override bool CanRead
        {
            get
            {
                return true;
            }
        }


        // Fields
        private int _length;
        private Queue _queue;

        // Nested Types
        private class Block
        {
            // Methods
            public Block(byte[] data)
            {
                this._data = data;
                this._offset = 0;
                this._length = this._data.Length;
            }

            public int Read(byte[] data, int offset, int count)
            {
                if (count > this._length)
                {
                    count = this._length;
                }
                Array.Copy(this._data, this._offset, data, offset, count);
                this._offset += count;
                this._length -= count;
                if (this._length == 0)
                {
                    this._data = null;
                }
                return count;
            }


            // Properties
            public bool IsEmpty
            {
                get
                {
                    return (this._data == null);
                }
            }


            // Fields
            private byte[] _data;
            private int _length;
            private int _offset;
        }
    }}

